let THREE=require('three');

/**
 * 碰撞体
 */
export default class RigidBody extends THREE.Object3D{
    constructor(){
        super();
        this._init();
    }

    //--------------------------------------对外属性及方法----------------------------------------

    /**
     * 设置目标对象的碰撞体为此碰撞体
     * @param object {Object3D}
     */
    set object(object){
        this._detach();
        this._attach(object);
    }

    /**
     * 获取绑定的对象
     * @returns {RigidBody._attach.props|*|null}
     */
    get object(){
        return this._target;
    }

    /**
     * 获取碰撞体的包围盒（世界空间）
     * @returns {Box3}
     */
    get bounds(){
        let box=new THREE.Box3();
        for(let collider of this._colliders){
            box.union(collider.bounds);
        }
        return box;
    }

    /**
     * 获取碰撞体的包围球
     * @returns {Sphere}
     */
    get sphere(){
        let s=new THREE.Sphere();
        this.bounds.getBoundingSphere(s);
        return s;
    }

    /**
     * 打开或关闭碰撞体中所有形状的调试
     * @param bol
     */
    set debug(bol){
        for(let collider of this._colliders){
            collider.debug=bol;
        }
    }

    /**
     * 获取碰撞体的所有碰撞体
     * @returns {null|[]}
     */
    get colliders(){
        return this._colliders;
    }

    /**
     * 获取碰撞体是否是静态的
     * @returns {*|null|boolean}
     */
    get isStatic(){
        return this._isStatic;
    }

    /**
     * 设置碰撞体是否静态
     * @param bol
     */
    set isStatic(bol){
        this._isStatic=bol;
    }

    /**
     * 获取射线检测函数
     * @returns {null|*}
     */
    get raycast(){
        return this._raycast;
    }

    /**
     * 检测与目标碰撞体是否碰撞
     * @param rigid
     * @returns {boolean}
     */
    check(rigid){
        for(let a of this._colliders){
            for(let b of rigid.colliders){
                if(a.check(b))return true;
            }
        }
        return false;
    }

    /**
     * 添加形状
     * @param colliders
     */
    addCollider(...colliders){
        for(let collider of colliders){
            let index=this._colliders.findIndex((s)=>s.uuid===collider.uuid);
            if(index!==-1)return;
            this._colliders.push(collider);
            collider.userData.rigid=this;
            this.add(collider);
            collider.updateMatrixWorld();
        }
    }

    /**
     * 移除形状
     * @param colliders
     */
    removeCollider(...colliders){
        for(let collider of colliders){
            let index=this._colliders.findIndex((s)=>s.uuid===collider.uuid);
            if(index===-1)return;
            collider.userData.rigid=null;
            this.remove(collider);
            this._colliders.splice(index,1);
        }
    }

    /**
     * 清除形状
     */
    clearCollider(){
        for(let collider of this._colliders){
            collider.userData.rigid=null;
            this.remove(collider);
        }
        this._colliders=[];
    }

    /**
     * 销毁
     */
    dispose(){
        this.clearCollider();
        this._colliders=null;
        this._isStatic=null;
        this._detach();
    }

    //--------------------------------------------私有属性及方法------------------------------------------------

    /**
     * 绑定对象
     * @param object
     * @private
     */
    _attach(object){
        if(!object)return;
        this._target=object;
        this._target.add(this);
        this.updateMatrixWorld();
        this._target.userData.rigid=this;
    }

    /**
     * 解除对象绑定
     * @private
     */
    _detach(){
        if(!this._target)return;
        this._target.remove(this);
        this._target.userData.rigid=null;
        this._target=null;
    }

    /**
     * 初始化
     * @private
     */
    _init(){
        this._initVariable();
        this._initRaycast();
    }

    /**
     * 初始化变量
     * @private
     */
    _initVariable(){
        this._target=null;
        this._colliders=[];
        this._isStatic=false;
        this._raycast=null;
    }

    /**
     * 初始化射线检测函数
     * @private
     */
    _initRaycast(){
        this._raycast=(raycaster,intersects)=> {
            for (let collider of this._colliders) {
                if (!collider.raycast) continue;
                collider.raycast(raycaster, intersects, this._target);
            }
        };
    }
}